/**
 * Copyright (c) 2010, Gaudenz Alder, David Benson
 */
package com.mxgraph.shape;

import com.mxgraph.canvas.mxGraphics2DCanvas;
import com.mxgraph.util.mxConstants;
import com.mxgraph.util.mxRectangle;
import com.mxgraph.util.mxUtils;
import com.mxgraph.view.mxCellState;

import java.awt.*;
import java.util.Map;

/**
 * The type Mx basic shape.
 */
public class mxBasicShape implements mxIShape {

    /**
     *
     */
    public void paintShape(mxGraphics2DCanvas canvas, mxCellState state) {
        Shape shape = createShape(canvas, state);

        if (shape != null) {
            // Paints the background
            if (configureGraphics(canvas, state, true)) {
                canvas.fillShape(shape, hasShadow(canvas, state));
            }

            // Paints the foreground
            if (configureGraphics(canvas, state, false)) {
                canvas.getGraphics().draw(shape);
            }
        }
    }

    /**
     * Create shape shape.
     *
     * @param canvas the canvas
     * @param state  the state
     * @return the shape
     */
    public Shape createShape(mxGraphics2DCanvas canvas, mxCellState state) {
        return null;
    }

    /**
     * Configures the graphics object ready to paint.
     *
     * @param canvas     the canvas to be painted to
     * @param state      the state of cell to be painted
     * @param background whether or not this is the background stage of                   the shape paint
     * @return whether or not the shape is ready to be drawn
     */
    protected boolean configureGraphics(mxGraphics2DCanvas canvas,
                                        mxCellState state, boolean background) {
        Map<String, Object> style = state.getStyle();

        if (background) {
            // Paints the background of the shape
            Paint fillPaint = hasGradient(canvas, state) ? canvas
                    .createFillPaint(getGradientBounds(canvas, state), style)
                    : null;

            if (fillPaint != null) {
                canvas.getGraphics().setPaint(fillPaint);

                return true;
            } else {
                Color color = getFillColor(canvas, state);
                canvas.getGraphics().setColor(color);

                return color != null;
            }
        } else {
            canvas.getGraphics().setPaint(null);
            Color color = getStrokeColor(canvas, state);
            canvas.getGraphics().setColor(color);
            canvas.getGraphics().setStroke(canvas.createStroke(style));

            return color != null;
        }
    }

    /**
     * Gets gradient bounds.
     *
     * @param canvas the canvas
     * @param state  the state
     * @return the gradient bounds
     */
    protected mxRectangle getGradientBounds(mxGraphics2DCanvas canvas,
                                            mxCellState state) {
        return state;
    }

    /**
     * Has gradient boolean.
     *
     * @param canvas the canvas
     * @param state  the state
     * @return the boolean
     */
    public boolean hasGradient(mxGraphics2DCanvas canvas, mxCellState state) {
        return true;
    }

    /**
     * Has shadow boolean.
     *
     * @param canvas the canvas
     * @param state  the state
     * @return the boolean
     */
    public boolean hasShadow(mxGraphics2DCanvas canvas, mxCellState state) {
        return mxUtils
                .isTrue(state.getStyle(), mxConstants.STYLE_SHADOW, false);
    }

    /**
     * Gets fill color.
     *
     * @param canvas the canvas
     * @param state  the state
     * @return the fill color
     */
    public Color getFillColor(mxGraphics2DCanvas canvas, mxCellState state) {
        return mxUtils.getColor(state.getStyle(), mxConstants.STYLE_FILLCOLOR);
    }

    /**
     * Gets stroke color.
     *
     * @param canvas the canvas
     * @param state  the state
     * @return the stroke color
     */
    public Color getStrokeColor(mxGraphics2DCanvas canvas, mxCellState state) {
        return mxUtils
                .getColor(state.getStyle(), mxConstants.STYLE_STROKECOLOR);
    }

}
